package com.weifly.weistock.optionvix;

import com.weifly.weistock.core.chart.bo.ChartDataSetBO;
import com.weifly.weistock.core.chart.bo.ChartSerieBO;
import com.weifly.weistock.core.common.Result;
import com.weifly.weistock.core.util.DateUtils;
import com.weifly.weistock.optionvix.bo.VixDayBO;
import com.weifly.weistock.optionvix.bo.VixDayExternalBO;
import com.weifly.weistock.optionvix.bo.VixYearBO;
import com.weifly.weistock.optionvix.dto.GetDayListRequest;
import org.apache.commons.lang3.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * converter
 *
 * @author weifly
 * Create at 2021/1/22
 */
public class OptionVixConverter {

    public static void updateDayOfYear(VixYearBO vixYear, VixDayBO vixDay) {
        VixDayBO targetDay = null;
        for (VixDayBO dayInYear : vixYear.getDayList()) {
            if (dayInYear.getDay().equals(vixDay.getDay())) {
                // 同一天
                targetDay = dayInYear;
                break;
            }
        }

        if (targetDay == null) {
            vixYear.getDayList().add(vixDay);
            // 记录排序
            vixYear.getDayList().sort(Comparator.comparing(VixDayBO::getDay));
        } else {
            targetDay.copyPropForm(vixDay);
        }
    }

    public static Result convertToVixDay(HttpServletRequest request, VixDayBO vixDay) {
        String dayField = request.getParameter("dayField");
        String error = DateUtils.checkDateString(dayField);
        if (error != null) {
            return Result.createErrorResult("日期错误：" + error);
        }
        vixDay.setDay(dayField);

        String openField = request.getParameter("openField");
        if (StringUtils.isBlank(openField)) {
            return Result.createErrorResult("缺少字段：开盘价");
        }
        double openValue = Double.parseDouble(openField);
        if (openValue <= 0) {
            return Result.createErrorResult("开盘价应大于0");
        }
        vixDay.setOpenValue(openValue);

        String highField = request.getParameter("highField");
        if (StringUtils.isBlank(highField)) {
            return Result.createErrorResult("缺少字段：最高价");
        }
        double highValue = Double.parseDouble(highField);
        if (highValue <= 0) {
            return Result.createErrorResult("最高价应大于0");
        }
        vixDay.setHighValue(highValue);

        String lowField = request.getParameter("lowField");
        if (StringUtils.isBlank(lowField)) {
            return Result.createErrorResult("缺少字段：最低价");
        }
        double lowValue = Double.parseDouble(lowField);
        if (lowValue <= 0) {
            return Result.createErrorResult("最低价应大于0");
        }
        vixDay.setLowValue(lowValue);

        String closeField = request.getParameter("closeField");
        if (StringUtils.isBlank(closeField)) {
            return Result.createErrorResult("缺少字段：收盘价");
        }
        double closeValue = Double.parseDouble(closeField);
        if (closeValue <= 0) {
            return Result.createErrorResult("收盘价应大于0");
        }
        vixDay.setCloseValue(closeValue);

        return null;
    }

    public static GetDayListRequest convertToGetDayListRequest(HttpServletRequest request, int limit) {
        GetDayListRequest req = new GetDayListRequest();
        String day = request.getParameter("day");
        if (StringUtils.isNotBlank(day)) {
            req.setDay(day);
        }
        req.setLimit(limit);
        return req;
    }

    public static Map<String, Object> convertToVixDayInfo(VixDayBO vixDay, VixDayExternalBO vixDayExternal) {
        Map<String, Object> dayInfo = new HashMap<>();
        dayInfo.put("day", vixDay.getDay());
        dayInfo.put("open", vixDay.getOpenValue());
        dayInfo.put("high", vixDay.getHighValue());
        dayInfo.put("low", vixDay.getLowValue());
        dayInfo.put("close", vixDay.getCloseValue());
        if (vixDayExternal != null) {
            dayInfo.put("diff", vixDayExternal.getDiff());
            dayInfo.put("rate", vixDayExternal.getRate());
            dayInfo.put("recentPercent", vixDayExternal.getRecentPercent());
            dayInfo.put("allPercent", vixDayExternal.getAllPercent());
        }
        return dayInfo;
    }

    public static double computePercent(int num1, int num2) {
        return computePercent(num1, new BigDecimal(num2));
    }

    public static double computePercent(int num1, BigDecimal num2) {
        return new BigDecimal(num1 * 100).divide(num2, 2, RoundingMode.HALF_UP).doubleValue();
    }

    public static void fillVixDataSet(ChartDataSetBO dataSet, List<VixDayBO> dayList) {
        if (dayList.isEmpty()) {
            return;
        }

        ChartSerieBO chartSerie = new ChartSerieBO();
        chartSerie.setName("VIX");
        chartSerie.setType("line");
        DecimalFormat decimalFormat = new DecimalFormat("0.####");
        for (VixDayBO dayBO : dayList) {
            dataSet.getPointList().add(dayBO.getDay());
            chartSerie.getDataList().add(Double.valueOf(decimalFormat.format(dayBO.getCloseValue())));
        }
        dataSet.getSerieList().add(chartSerie);
    }

    public static void fillPercentDataSet(ChartDataSetBO dataSet, OptionVixMonitorService optionVixMonitorService) {
        if (dataSet.getPointList().isEmpty()) {
            return; // 无坐标数据
        }

        ChartSerieBO recentSerie = new ChartSerieBO();
        recentSerie.setName("recent");
        recentSerie.setType("line");
        dataSet.getSerieList().add(recentSerie);
        ChartSerieBO allSerie = new ChartSerieBO();
        allSerie.setName("all");
        allSerie.setType("line");
        dataSet.getSerieList().add(allSerie);
        for (String point : dataSet.getPointList()) {
            VixDayExternalBO dayExternal = optionVixMonitorService.getVixDayExternal(point);
            recentSerie.getDataList().add(dayExternal == null ? 0 : dayExternal.getRecentPercent());
            allSerie.getDataList().add(dayExternal == null ? 0 : dayExternal.getAllPercent());
        }
    }
}
